**********************************************************************************************************
** Article: Is it Possible to Predict Electoral Abstention on the Individual Level?						**
**			A Preregistered Test on Forecasting the Effects of Abolishing Compulsory Voting in Belgium	**
** Journal: International Journal of Forecasting														**
** Date:	April 2025		 																			**
** Authors:	Stiers & Hooghe																				**
**********************************************************************************************************

*** Replication of analyses prediction model: General results (Figure 3, Table 3, Table 4) ***
***Load dataset
use "Replication_analysis_Model_A.dta"

***Figure showing prediction by turnout group (Figure 3)
*Histogram Model A
twoway (hist predictedturnout_BES if W4_turnout==1 , percent width(0.01) color(gs13)) (hist predictedturnout_BES if W4_turnout==2 , percent width(0.01) color(gs5%50)) , legend(order(1 "Voted" 2 "Did not vote") pos(6) r(1)) name(F1,replace) fxsize(150)
*Boxplot Model A
graph box predictedturnout_BES , over(W4_turnout,relabel(1 "Voted" 2 "Did not vote")) ytitle("Predicted likelihood turnout") name(F2,replace) fxsize(100)
*Combine top part of Figure 3
graph combine F1 F2 , title("Model A",size(medium)) name(Figure1,replace)

*Histogram Model B
twoway (hist predictedturnout_ESS if W4_turnout==1 , percent width(0.01) color(gs13)) (hist predictedturnout_BES if W4_turnout==2 , percent width(0.01) color(gs5%50)) ,  legend(order(1 "Voted" 2 "Did not vote") pos(6) r(1)) name(F3,replace) fxsize(150)
*Boxplot Model B
graph box predictedturnout_ESS , over(W4_turnout,relabel(1 "Voted" 2 "Did not vote")) ytitle("Predicted likelihood turnout") name(F4,replace) fxsize(100)
*Combine bottom part of Figure 3
graph combine F3 F4 , title("Model B",size(medium)) name(Figure2,replace)

*Full Figure 3
grc1leg2 Figure1 Figure2 , c(1) pos(7) ysize(5) iscale(0.75)


***T-tests (Table 3)
*Unweighted
//Model A
ttest predictedturnout_BES , by(W4_turnout)
//Model B
ttest predictedturnout_ESS , by(W4_turnout)

*Weighted
*Model A
reg predictedturnout_BES i.W4_turnout [pweight=Weight]
margins W4_turnout
//Model B
reg predictedturnout_ESS i.W4_turnout [pweight=Weight]
margins W4_turnout


***Cross-table (Table 4)
svyset [pweight=Weight]
*Model A
tab groups_BES W4_turnout , r chi	//Unweighted
svy: tab groups_BES W4_turnout if groups_BES==1	//For weighted row percentages
svy: tab groups_BES W4_turnout if groups_BES==2	//For weighted row percentages
svy: tab groups_BES W4_turnout if groups_BES==3	//For weighted row percentages
svy: tab groups_BES W4_turnout	//For weighted total row percentages	
*Model B
tab groups_ESS W4_turnout , r chi	//Unweighted
svy: tab groups_ESS W4_turnout if groups_ESS==1	//For weighted row percentages
svy: tab groups_ESS W4_turnout if groups_ESS==2	//For weighted row percentages
svy: tab groups_ESS W4_turnout if groups_ESS==3	//For weighted row percentages
svy: tab groups_ESS W4_turnout	//For weighted total row percentages	


***Models including interactions: Model A (Table A.1 in Appendix A and Figure 4)
*Model 1
logit Turnout c.Age##i.Dataset Age2 i.Gender i.Education Income Interest i.PartyID Trust Knowledge i.Past_turnout
//Marginal effects
margins, dydx(Age) at(Dataset=(0 1))
//Figure 4 top left
marginsplot , scheme(s1mono) recast(scatter) title("Age") ytitle("AME") xtitle("Dataset") xscale(range(-0.3 1.3)) yline(0,lpattern(shortdash)) name(F1,replace)

*Model 2
logit Turnout Age c.Age2##i.Dataset i.Gender i.Education Income Interest i.PartyID Trust Knowledge i.Past_turnout
//Marginal effects
margins, dydx(Age2) at(Dataset=(0 1))
//Figure 4 top right
marginsplot , scheme(s1mono) recast(scatter) title("Age2") ytitle("AME") xtitle("Dataset") xscale(range(-0.3 1.3)) yline(0,lpattern(shortdash)) name(F2,replace)

*Model 3
logit Turnout Age Age2 i.Gender##i.Dataset i.Education Income Interest i.PartyID Trust Knowledge i.Past_turnout

*Model 4
logit Turnout Age Age2 i.Gender i.Education##i.Dataset Income Interest i.PartyID Trust Knowledge i.Past_turnout

*Model 5
logit Turnout Age Age2 i.Gender i.Education c.Income##i.Dataset Interest i.PartyID Trust Knowledge i.Past_turnout

*Model 6
logit Turnout Age Age2 i.Gender i.Education Income c.Interest##i.Dataset i.PartyID Trust Knowledge i.Past_turnout
//Marginal effects
margins, dydx(Interest) at(Dataset=(0 1))
//Figure 4 bottom left
marginsplot , scheme(s1mono) recast(scatter) title("Interest in politics") ytitle("AME") xtitle("Dataset") xscale(range(-0.3 1.3)) yline(0,lpattern(shortdash)) name(F3,replace)

*Model 7
logit Turnout Age Age2 i.Gender i.Education Income Interest i.PartyID##i.Dataset Trust Knowledge i.Past_turnout

*Model 8
logit Turnout Age Age2 i.Gender i.Education Income Interest i.PartyID c.Trust##i.Dataset Knowledge i.Past_turnout

*Model 9
logit Turnout Age Age2 i.Gender i.Education Income Interest i.PartyID Trust c.Knowledge##i.Dataset i.Past_turnout

*Model 10
logit Turnout Age Age2 i.Gender i.Education Income Interest i.PartyID Trust Knowledge i.Past_turnout##i.Dataset
//Marginal effects
margins Past_turnout , at(Dataset=(0 1))
//Figure 4 bottom right
marginsplot , scheme(s1mono) recast(scatter) title("Past turnout") ytitle("Predicted probability") xtitle("Dataset") xscale(range(-0.3 1.3)) legend(pos(6) r(1)) plot( , label("Voted" "Not voted" "Not allowed to vote")) name(F4,replace)

*Full Figure 4
graph combine F1 F2 F3 F4 , scheme(s1mono) iscale(0.65)


***Models including interactions: Model B (Table A.2 in Appendix A and Figure 5)
*Load dataset
use "Replication_analysis_Model_B.dta"

*Model 1
logit Turnout c.Age##i.Dataset Age2 i.Gender i.Education Income Interest i.PartyID Trust i.countrydummy2 i.countrydummy3 i.countrydummy4 , cluster(cntry)

*Model 2
logit Turnout Age c.Age2##i.Dataset i.Gender i.Education Income Interest i.PartyID Trust i.countrydummy2 i.countrydummy3 i.countrydummy4 , cluster(cntry)

*Model 3
logit Turnout Age Age2 i.Gender##i.Dataset i.Education Income Interest i.PartyID Trust i.countrydummy2 i.countrydummy3 i.countrydummy4 , cluster(cntry)
//Marginal effects
margins , dydx(Gender) at(Dataset=(0 1))
//Figure 5 top left
marginsplot , scheme(s1mono) recast(scatter) title("Gender") ytitle("AME") xtitle("Dataset") xscale(range(-0.3 1.3)) yline(0,lpattern(shortdash)) name(F1,replace) fysize(50)

*Model 4
logit Turnout Age Age2 i.Gender i.Education##i.Dataset Income Interest i.PartyID Trust i.countrydummy2 i.countrydummy3 i.countrydummy4 , cluster(cntry)
//Marginal effects
margins Education , at(Dataset=(0 1))
//Figure 5 right
marginsplot , scheme(s1mono) recast(scatter) title("Educational level") ytitle("Predicted probability") xtitle("Dataset") xscale(range(-0.3 1.3)) legend(pos(6) r(1)) plot( , label("Low" "Middle" "High")) name(F2,replace) fysize(50)

*Model 5
logit Turnout Age Age2 i.Gender i.Education c.Income##i.Dataset Interest i.PartyID Trust i.countrydummy2 i.countrydummy3 i.countrydummy4 , cluster(cntry)

*Model 6
logit Turnout Age Age2 i.Gender i.Education Income c.Interest##i.Dataset i.PartyID Trust i.countrydummy2 i.countrydummy3 i.countrydummy4 , cluster(cntry)
//Marginal effects
margins, dydx(Interest) at(Dataset=(0 1))
//Figure 5 bottom left
marginsplot , scheme(s1mono) recast(scatter) title("Interest in politics") ytitle("AME") xtitle("Dataset") xscale(range(-0.3 1.3)) name(F3,replace) fysize(50)

*Model 7
logit Turnout Age Age2 i.Gender i.Education Income Interest i.PartyID##i.Dataset Trust i.countrydummy2 i.countrydummy3 i.countrydummy4 , cluster(cntry)

*Model 8
logit Turnout Age Age2 i.Gender i.Education Income Interest i.PartyID c.Trust##i.Dataset i.countrydummy2 i.countrydummy3 i.countrydummy4 , cluster(cntry)

*Final Figure 5
graph combine F1 F3 , name(fig1,replace) col(1) iscale(1)
graph combine fig1 F2 , row(1)



*** Appendices ***
*Appendix A: see code above

*Appendix B
use "Replication_analysis_Model_A.dta",clear
//Table B.1
keep if groups_BES~=.
svyset [pweight=Weight]
ttest predictedturnout_BES , by(panelrespondent)
ttest predictedturnout_ESS , by(panelrespondent)
reg predictedturnout_BES i.panelrespondent [pweight=Weight]
margins panelrespondent
reg predictedturnout_ESS i.panelrespondent [pweight=Weight]
margins panelrespondent

//Table B.2
tab groups_BES panelrespondent , col chi
tab groups_ESS panelrespondent , col chi
svy: tab groups_BES panelrespondent , col
svy: tab groups_ESS panelrespondent , col

*Appendix C
//Figure C.1
use "Replication_analysis_Model_B.dta",clear
graph bar Turnout , over(cntry) ytitle("Proportion turnout") ylabel(0(0.2)1) scheme(lean1)
//Tabel C.1
tab cntry Turnout , r

//Appendix D: See replication file predictions

